﻿/*----------------------------------------------------------------
           // Copyright (C) 2008 安华顺通(北京)科技有限公司
           // 版权所有。 
           //
           // 文件名：SysCompilerEnum.cs
           // 文件功能描述：扩展类型编译功能。
           //
           // 
           // 创建标识：周玉偈20081028
           //
           // 修改标识
           // 修改描述：
           //
           // 修改标识：
           // 修改描述：
//----------------------------------------------------------------*/

#region UsingStatements

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Windows.Forms;
using Microsoft.CSharp;
using RuleCode.ObjectTree;
using System.Collections.Generic;

#endregion

namespace RuleCode.compiler
{
    public class SysCompilerEnum
    {
        private static SysCompilerEnum sysCompilerEnum;
        private static readonly string EDTPath =Util.GetEnumsPath +"\\";// Util.OTPath + "\\Module\\Enums\\";
        private static readonly string keyFile = "D:\\snk\\RuleCode.Query.snk";
        public static SysCompilerEnum Instance
        {
            get
            {
                if (sysCompilerEnum == null)
                {
                    sysCompilerEnum = new SysCompilerEnum();
                }
                return sysCompilerEnum;
            }
        }

        public void compileEnum(SysTreeNode node)
        {
            #region 初始化环境
            node.Expand();
            Util.SetPropertyContent(node);
            string name = node.Text;
            string op;
            CodeCompileUnit CompileUnit = new CodeCompileUnit(); //编译单元容器
            CodeNamespace typeNameSpace = new CodeNamespace(Util.RootClassNameSpace+".Enum"); //命名空间
            CompileUnit.Namespaces.Add(typeNameSpace);
            CodeTypeDeclaration type = new CodeTypeDeclaration(name); //类定义，Name是类名称
            //设置类的继承。
            type.Attributes = MemberAttributes.Public;
            type.IsClass = true;
            type.BaseTypes.Add("RuleCode.Common.BaseEnum");

            // 将类型加入到容器的类型集合中
            typeNameSpace.Types.Add(type);


            //命名空间里面的引用，注意：引用在空间里面，单元里面；
            typeNameSpace.Imports.Add(new CodeNamespaceImport("System"));
            typeNameSpace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
            typeNameSpace.Imports.Add(new CodeNamespaceImport("System.Text"));
            typeNameSpace.Imports.Add(new CodeNamespaceImport("System.ComponentModel"));
            typeNameSpace.Imports.Add(new CodeNamespaceImport("System.Data"));
            typeNameSpace.Imports.Add(new CodeNamespaceImport("RuleCode.Common"));
            typeNameSpace.Imports.Add(new CodeNamespaceImport("RuleCode.ObjectTree"));

            //增加默认构造器
            // Declare a constructor that takes a string argument and calls the base class constructor with it.
            CodeConstructor baseStringConstructor = new CodeConstructor();
            baseStringConstructor.Attributes = MemberAttributes.Public;
            // Calls a base class constructor with the TestStringParameter parameter.
            baseStringConstructor.BaseConstructorArgs.Add(new CodeVariableReferenceExpression());
            // Adds the constructor to the Members collection of the DerivedType.
            type.Members.Add(baseStringConstructor);

            #endregion

            #region 枚举节点

            BaseEnumProperty baseEnumProperty;
            baseEnumProperty = (BaseEnumProperty)node.Property;

            type.Comments.Add(new CodeCommentStatement("<summary>", true));
            type.Comments.Add(new CodeCommentStatement("Enum:"+baseEnumProperty .LabelText+","+node.Nodes.Count.ToString () +" Fields" ,true ));
            type.Comments.Add(new CodeCommentStatement("</summary>", true));


            op =
                @"
                public override RuleCode.Common.BaseEnumProperty BaseEnumProperty
                {
                    get
                    {
                        if (this.baseEnumProperty == null)
                            this.baseEnumProperty = new RuleCode.Common.BaseEnumProperty();
                ";
            op += "        this.baseEnumProperty.DisplayLength = \"" + baseEnumProperty.DisplayLength + "\";" +
                  Environment.NewLine;
            op += "        this.baseEnumProperty.ID = \"" + baseEnumProperty.ID + "\";" + Environment.NewLine;
            op += "        this.baseEnumProperty.Label = \"" + baseEnumProperty.Label + "\";" + Environment.NewLine;
            op += "        this.baseEnumProperty.Name = \"" + baseEnumProperty.Name + "\";" + Environment.NewLine;
            op += "        this.baseEnumProperty.Style = \"" + baseEnumProperty.Style + "\";" + Environment.NewLine;
            op += "        this.baseEnumProperty.UseEnumValue = true ;" + Environment.NewLine;
            op +=
                @"        if (this.baseEnumProperty.EnumatorPropertyList == null)
                    this.baseEnumProperty.EnumatorPropertyList = new List<EnumatorProperty>();
                    this.baseEnumProperty.EnumatorPropertyList.Clear();
                    RuleCode.Common.EnumatorProperty enumatorProperty;
                    " +
                Environment.NewLine;
            BaseEnumElementProperty baseEnumElementProperty;
            node.ExpandAll();

            //Modified By DingyuLiang  2009-03-06
            List<string> propertyStrings = new List<string>();
            //End


            foreach (SysTreeNode sNode in node.Nodes)
            {
                Util.SetPropertyInSilent = true;
                Util.SetPropertyContent(sNode);
                Util.SetPropertyInSilent = false;
                baseEnumElementProperty = (BaseEnumElementProperty)sNode.Property;
                op += "        enumatorProperty = new EnumatorProperty();" + Environment.NewLine;
                op += "        enumatorProperty.EnumValue = " + baseEnumElementProperty.EnumValue + ";" + Environment.NewLine;
                op += "        enumatorProperty.ID = \"" + baseEnumElementProperty.ID + "\";" + Environment.NewLine;
                op += "        enumatorProperty.Label = \"" + baseEnumElementProperty.Label + "\";" + Environment.NewLine;
                op += "        enumatorProperty.Name = \"" + baseEnumElementProperty.Name + "\";" + Environment.NewLine;
                op += "        this.baseEnumProperty.EnumatorPropertyList.Add(enumatorProperty);" + Environment.NewLine;

                //Modified By DingyuLiang  2009-03-06
                string propertyArg = string.Empty;
                propertyArg += "        /// <summary>" + Environment.NewLine;
                propertyArg += "        /// " + baseEnumElementProperty.EnumValue.ToString() +" , " + RuleCode.Common.SystemLanguage.Instance.GetLabel(baseEnumElementProperty.Label) + Environment.NewLine;
                propertyArg += "        /// </summary>" + Environment.NewLine;
                propertyArg += "        public static int " + baseEnumElementProperty.Name + "{ get { return " + baseEnumElementProperty.EnumValue.ToString() + ";}}" + Environment.NewLine;
                propertyStrings.Add(propertyArg);
                //End
            }

            op +=
                @"
                    return this.baseEnumProperty;
                }
                set
                {
                    this.baseEnumProperty = value;
                }
            }
                ";
            type.Members.Add(new CodeSnippetTypeMember(op));

            //Modified By DingyuLiang  2009-03-06
            foreach (string propertyString in propertyStrings)
                type.Members.Add(new CodeSnippetTypeMember(propertyString ));
            //End

            #endregion

            #region 输出与编译

            //编译环境变量
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CodeGeneratorOptions options = new CodeGeneratorOptions();
            options.BlankLinesBetweenMembers = false;
            options.IndentString = "\t";

            //编译参数
            //相当于项目下的“引用”部分
            CompilerParameters cp = new CompilerParameters();
            cp.OutputAssembly = Util.GetEnumsPath + "\\" + name;// Util.OTPath + "\\Module\\Enums\\" + name;
            cp.ReferencedAssemblies.Add("System.dll");
            cp.ReferencedAssemblies.Add("System.Data.dll");
            cp.ReferencedAssemblies.Add("System.Xml.dll");
            cp.ReferencedAssemblies.Add("mscorlib.dll");
            cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            cp.ReferencedAssemblies.Add("RuleCode.Common.dll");
            //cp.ReferencedAssemblies.Add("RuleCode.ObjectTree");

            cp.WarningLevel = 3;


            cp.CompilerOptions = "/target:module /optimize /moduleassemblyname:Enum.dll";
            cp.GenerateExecutable = false;
            cp.GenerateInMemory = false;

            TempFileCollection tfc = new TempFileCollection(Application.StartupPath, false);
            CompilerResults cr = new CompilerResults(tfc);
            CSharpCodeProvider csp = new CSharpCodeProvider();
            DirectoryInfo EDTDir = new DirectoryInfo(EDTPath);
            if (!EDTDir.Exists)
            {
                EDTDir.Create();
            }
            IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter(EDTPath + name + ".cs", false), "    ");
            csp.GenerateCodeFromCompileUnit(CompileUnit, tw, new CodeGeneratorOptions());
            tw.Close();

            #endregion


            //将编译 好的文件添加到项目中
            if (Util_DTE.IsAddToProjectAtCompiled)
                Util_DTE.AddGeneratedFileToProject(node, GenerateFileType.Enum);
        }

        public void compileEnums(SysTreeNode node)
        {
            node.Expand();
            foreach (SysTreeNode snode in node.Nodes)
            {
                compileEnum(snode);
            }
        }
    }
}